package com.cema.manage.project.system.user.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.cema.manage.framework.web.controller.BaseController;
import com.cema.manage.project.enums.*;
import com.cema.manage.project.manage.adRecord.domain.AdRecord;
import com.cema.manage.project.manage.adRecord.service.IAdRecordService;
import com.cema.manage.project.manage.adRecordSecondary.domain.AdRecordSecondary;
import com.cema.manage.project.manage.adRecordSecondary.service.IAdRecordSecondaryService;
import com.cema.manage.project.manage.userDailyActivity.domain.UserDailyActivity;
import com.cema.manage.project.manage.userDailyActivity.service.IUserDailyActivityService;
import com.cema.manage.project.manage.users.domain.Users;
import com.cema.manage.project.manage.users.service.IUsersService;
import com.cema.manage.project.manage.withdrawalRecord.domain.WithdrawalRecord;
import com.cema.manage.project.manage.withdrawalRecord.service.IWithdrawalRecordService;
import com.cema.manage.project.system.menu.domain.Menu;
import com.cema.manage.project.system.menu.service.IMenuService;
import com.cema.manage.project.system.user.domain.User;
import com.cema.manage.project.system.user.domain.UserRole;
import com.cema.manage.project.system.user.domain.UsersLogin;
import com.cema.manage.project.system.user.mapper.UserRoleMapper;
import com.cema.manage.project.util.DateUtils;
import com.cema.manage.redis.RedisService;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * 首页 业务处理
 *
 * @author reasahi
 */
@Controller
public class IndexController extends BaseController {
    @Autowired
    private IMenuService menuService;

    @Resource
    private IAdRecordService adRecordService;

    @Resource
    private IAdRecordSecondaryService adRecordSecondaryService;

    @Resource
    private IWithdrawalRecordService withdrawalRecordService;

    @Resource
    private IUsersService iUsersService;

    @Resource
    private IUserDailyActivityService userDailyActivityService;

    @Autowired
    private com.cema.manage.framework.config.reasahiConfig reasahiConfig;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private RedisService redisService;

    // 系统首页
    @GetMapping("/index")
    public String index(Model model) {
        // 取身份信息
        User user = getUser();
        if (ObjectUtil.isNull(user)) {
            return "error/unauth";
        }
        // 根据用户id取出菜单
        List<Menu> menus = menuService.selectMenusByUserId(user.getUserId());
        model.addAttribute("menus", menus);
        model.addAttribute("user", user);
        model.addAttribute("copyrightYear", reasahiConfig.getCopyrightYear());

        model.addAttribute("appName", redisService.get(RedisEnum.APP_NAME.getKey()));
        return "index";
    }

    /**
     * 系统介绍
     *
     * @param model
     * @return
     */
    @GetMapping("/system/main")
    public String main(Model model) {
        EntityWrapper<UserRole> userRoleEntityWrapper = new EntityWrapper<>();
        if (ObjectUtil.isNull(getUser())) {
            return "error/unauth";
        }
        userRoleEntityWrapper.eq("user_id", getUserId());
        userRoleEntityWrapper.eq("role_id", 4);
        int count = userRoleMapper.selectCount(userRoleEntityWrapper);
        if (count != 0) {
            model.addAttribute("data", iUsersService.toProxyStatistics(getUser().getPlUserId()));
            return "proxy";
        }
        EntityWrapper<AdRecord> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("ar_callback", CallbackAdRecordEnum.CALLBACK_YES.getValue());
        DateUtils.getCurrentDayTime(entityWrapper, "create_time");
        List<AdRecord> adRecordList = adRecordService.selectList(entityWrapper);
        EntityWrapper<AdRecordSecondary> adRecordSecondaryEntityWrapper = new EntityWrapper<>();
        DateUtils.getCurrentDayTime(adRecordSecondaryEntityWrapper, "create_time");
        List<AdRecordSecondary> adRecordSecondaryList = adRecordSecondaryService.selectList(adRecordSecondaryEntityWrapper);
        //比例
        int proportion = 10000;
        //总收益
//        BigDecimal totalRevenue = BigDecimal.ZERO;
        //今日总收益
        BigDecimal todayTotalRevenue = BigDecimal.ZERO;
        //用户总收益
//        BigDecimal userTotalRevenue = BigDecimal.ZERO;
        //今日用户收益
        BigDecimal userTodayTotalRevenue = BigDecimal.ZERO;
        //穿三甲总收益
        //BigDecimal csjTotalRevenue = BigDecimal.ZERO;
        //今日穿三甲总收益
        BigDecimal csjTodayTotalRevenue = BigDecimal.ZERO;
        //优量汇总收益
        // BigDecimal ylhTotalRevenue = BigDecimal.ZERO;
        //今日优量汇总收益
        BigDecimal ylhTodayTotalRevenue = BigDecimal.ZERO;
        //快手总收益
        //BigDecimal ksTotalRevenue = BigDecimal.ZERO;
        //今日快手总收益
        BigDecimal ksTodayTotalRevenue = BigDecimal.ZERO;
        BigDecimal otherTodayTotalRevenue = BigDecimal.ZERO;
        //广告总条数
        //int totalRevenueCount = 0;
        //今日广告总条数
        int todayTotalRevenueCount = 0;
        if (ObjectUtil.isNotNull(adRecordList)) {
            todayTotalRevenueCount = adRecordList.size()+adRecordSecondaryList.size();
            int totalRevenueSum = adRecordList.stream().mapToInt(AdRecord::getArRealityMoney).sum();
            totalRevenueSum = totalRevenueSum + adRecordSecondaryList.stream().mapToInt(AdRecordSecondary::getArsRealityMoney).sum();
            int userTotalRevenueSum = adRecordList.stream().mapToInt(AdRecord::getUsMoney).sum();
            todayTotalRevenue = BigDecimal.valueOf(totalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            userTodayTotalRevenue = BigDecimal.valueOf(userTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            //今天收益记录
//            List<AdRecord> todayAdRecord = adRecordList.stream().filter(adRecord -> DateUtil.isSameDay(adRecord.getCreateTime(), new Date())).collect(Collectors.toList());
//            if (ObjectUtil.isNotNull(todayAdRecord)) {
//                todayTotalRevenueCount = todayAdRecord.size();
//                int todayTotalRevenueSum = todayAdRecord.stream().mapToInt(AdRecord::getArRealityMoney).sum();
//                int userTodayTotalRevenueSum = todayAdRecord.stream().mapToInt(AdRecord::getUsMoney).sum();
//                todayTotalRevenue = BigDecimal.valueOf(todayTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
//                userTodayTotalRevenue = BigDecimal.valueOf(userTodayTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
//            }
            //渠道收益
            List<AdRecord> channelGdtAdRecordList = adRecordList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_GDT.getValue().equals(adRecord.getArChannel())).collect(Collectors.toList());
            List<AdRecordSecondary> adRecordSecondaryListYlh = adRecordSecondaryList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_GDT.getValue().equals(adRecord.getArsChannel())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(channelGdtAdRecordList)) {
                int ylhTotalRevenueSum = channelGdtAdRecordList.stream().mapToInt(AdRecord::getArRealityMoney).sum();
                ylhTotalRevenueSum = ylhTotalRevenueSum + adRecordSecondaryListYlh.stream().mapToInt(AdRecordSecondary::getArsRealityMoney).sum();
                // int totalCount = totalCount(channelGdtAdRecordList);
                ylhTodayTotalRevenue = BigDecimal.valueOf(ylhTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
                //ylhTodayTotalRevenue = BigDecimal.valueOf(totalCount).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            }
            List<AdRecord> channelLsAdRecordList = adRecordList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_KS.getValue().equals(adRecord.getArChannel())).collect(Collectors.toList());
            List<AdRecordSecondary> adRecordSecondaryListks = adRecordSecondaryList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_KS.getValue().equals(adRecord.getArsChannel())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(channelLsAdRecordList)) {
                int ksTotalRevenueSum = channelLsAdRecordList.stream().mapToInt(AdRecord::getArRealityMoney).sum();
                //  int totalCount = totalCount(channelLsAdRecordList);
                ksTotalRevenueSum = ksTotalRevenueSum + adRecordSecondaryListks.stream().mapToInt(AdRecordSecondary::getArsRealityMoney).sum();
                ksTodayTotalRevenue = BigDecimal.valueOf(ksTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
                //ksTodayTotalRevenue = BigDecimal.valueOf(totalCount).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            }
            List<AdRecord> channelPangleAdRecordList = adRecordList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_PANGLE.getValue().equals(adRecord.getArChannel())).collect(Collectors.toList());
            List<AdRecordSecondary> adRecordSecondaryListCsj = adRecordSecondaryList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_PANGLE.getValue().equals(adRecord.getArsChannel())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(channelPangleAdRecordList)) {
                int csjTotalRevenueSum = channelPangleAdRecordList.stream().mapToInt(AdRecord::getArRealityMoney).sum();
                // int totalCount = totalCount(channelPangleAdRecordList);
                csjTotalRevenueSum = csjTotalRevenueSum + adRecordSecondaryListCsj.stream().mapToInt(AdRecordSecondary::getArsRealityMoney).sum();
                csjTodayTotalRevenue = BigDecimal.valueOf(csjTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
                //csjTodayTotalRevenue = BigDecimal.valueOf(totalCount).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            }

            List<AdRecord>  otherAdRecordList = adRecordList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_OTHER.getValue().equals(adRecord.getArChannel())).collect(Collectors.toList());
            List<AdRecordSecondary>  otherSecondaryListCsj = adRecordSecondaryList.stream().filter(adRecord -> AdChannelEnum.AD_CHANNEL_OTHER.getValue().equals(adRecord.getArsChannel())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(otherAdRecordList)) {
                int csjTotalRevenueSum = otherAdRecordList.stream().mapToInt(AdRecord::getArRealityMoney).sum();
                // int totalCount = totalCount(channelPangleAdRecordList);
                csjTotalRevenueSum = csjTotalRevenueSum + otherSecondaryListCsj.stream().mapToInt(AdRecordSecondary::getArsRealityMoney).sum();
                otherTodayTotalRevenue = BigDecimal.valueOf(csjTotalRevenueSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
                //csjTodayTotalRevenue = BigDecimal.valueOf(totalCount).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            }
        }
        model.addAttribute("version", reasahiConfig.getVersion());
        // model.addAttribute("totalRevenue", totalRevenue);
        model.addAttribute("todayTotalRevenue", todayTotalRevenue);
        // model.addAttribute("userTotalRevenue", userTotalRevenue);
        model.addAttribute("userTodayTotalRevenue", userTodayTotalRevenue);
        // model.addAttribute("csjTotalRevenue", csjTotalRevenue);
        model.addAttribute("csjTodayTotalRevenue", csjTodayTotalRevenue);
        //  model.addAttribute("ylhTotalRevenue", ylhTotalRevenue);
        model.addAttribute("ylhTodayTotalRevenue", ylhTodayTotalRevenue);
        //  model.addAttribute("ksTotalRevenue", ksTotalRevenue);
        model.addAttribute("ksTodayTotalRevenue", ksTodayTotalRevenue);
        // model.addAttribute("totalRevenueCount", totalRevenueCount);
        model.addAttribute("todayTotalRevenueCount", todayTotalRevenueCount);
        model.addAttribute("otherTodayTotalRevenue", otherTodayTotalRevenue);
        BigDecimal ecpm = BigDecimal.ZERO;
        if (todayTotalRevenueCount > 0) {
            ecpm = todayTotalRevenue.divide(BigDecimal.valueOf(todayTotalRevenueCount), 2, RoundingMode.DOWN);
        }
        model.addAttribute("ecpm", ecpm.multiply(BigDecimal.valueOf(100)));
//////////////////////////////////// 广告记录 end ///////////////////////////////////
        //  BigDecimal totalWithdrawal = BigDecimal.ZERO;
        BigDecimal totalTodayWithdrawal = BigDecimal.ZERO;
        EntityWrapper<WithdrawalRecord> entityWrapperWithdrawal = new EntityWrapper<>();
        DateUtils.getCurrentDayTime(entityWrapperWithdrawal, "create_time");
        List<WithdrawalRecord> withdrawalRecordList = withdrawalRecordService.selectList(entityWrapperWithdrawal);
        if (ObjectUtil.isNotNull(withdrawalRecordList)) {
            List<WithdrawalRecord> withdrawalRecords = withdrawalRecordList.stream().filter(withdrawalRecord -> ToExamineEnum.TO_EXAMINE_RED_ENVELOPE.getValue().equals(withdrawalRecord.getWrStatus())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(withdrawalRecords)) {
                int totalWithdrawalSum = withdrawalRecords.stream().mapToInt(WithdrawalRecord::getWrMoney).sum();
                totalTodayWithdrawal = BigDecimal.valueOf(totalWithdrawalSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            }
            //今天收益记录
//            List<WithdrawalRecord> todayList = withdrawalRecordList.stream().filter(withdrawalRecord ->
//                    DateUtil.isSameDay(withdrawalRecord.getCreateTime(), new Date())
//                            && ToExamineEnum.TO_EXAMINE_GOLD_COINS.getValue().equals(withdrawalRecord.getWrStatus())).collect(Collectors.toList());
//            if (ObjectUtil.isNotNull(todayList)) {
//                int totalTodayWithdrawalSum = todayList.stream().mapToInt(WithdrawalRecord::getWrMoney).sum();
//                totalTodayWithdrawal = BigDecimal.valueOf(totalTodayWithdrawalSum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
//            }
        }
//        model.addAttribute("totalWithdrawal", totalWithdrawal);
        model.addAttribute("totalTodayWithdrawal", totalTodayWithdrawal);
        //////////////////////////////////// 提现记录 end ///////////////////////////////////
        EntityWrapper<Users> usersEntityWrapper = new EntityWrapper<>();
        usersEntityWrapper.eq("status", UserStatusEnum.USER_STATUS_NORMAL.getValue());
        List<Users> usersList = iUsersService.selectList(usersEntityWrapper);
        //总用户
        int totalUser = 0;
        //用户剩余总金额
        //BigDecimal totalUserMoney = BigDecimal.ZERO;
        //三日新增
        int threeDayAddition = 0;
        //七日新增
        int sevenDayAddition = 0;
        //今日登录用户
        int todayLoginUser = 0;
        //今日新增用户
        int todayInsertUser = 0;
        if (ObjectUtil.isNotNull(usersList)) {
            totalUser = usersList.size();
            //int goldCoin = usersList.stream().mapToInt(Users::getMoneyGoldCoin).sum();
            //int rRedPacket = usersList.stream().mapToInt(Users::getMoneyRedPacket).sum();
            //int totalUserMoneySum = goldCoin + rRedPacket;
            //totalUserMoney = BigDecimal.valueOf(totalUserMoneySum).divide(BigDecimal.valueOf(proportion), 2, RoundingMode.DOWN);
            //三天新增
            List<Users> threeUserList = usersList.stream().filter(users ->
                    ChronoUnit.DAYS.between(users.getCreateTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate(), LocalDate.now()) <= 2).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(threeUserList)) {
                threeDayAddition = threeUserList.size();
            }
            //七天新增
            List<Users> sevenUserList = usersList.stream().filter(users ->
                    ChronoUnit.DAYS.between(users.getCreateTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate(), LocalDate.now()) <= 6).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(sevenUserList)) {
                sevenDayAddition = sevenUserList.size();
            }
            //今日登录用户
            List<Users> todayLoginList = usersList.stream().filter(users ->
                    DateUtil.isSameDay(new Date(), users.getLoginTime())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(todayLoginList)) {
                todayLoginUser = todayLoginList.size();
            }
            //今日新增用户
            List<Users> todayInsertList = usersList.stream().filter(users ->
                    DateUtil.isSameDay(new Date(), users.getCreateTime())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(todayInsertList)) {
                todayInsertUser = todayInsertList.size();
            }
        }
        model.addAttribute("totalUser", totalUser);
        // model.addAttribute("totalUserMoney", totalUserMoney);
        model.addAttribute("threeDayAddition", threeDayAddition);
        model.addAttribute("sevenDayAddition", sevenDayAddition);
        model.addAttribute("todayLoginUser", todayLoginUser);
        model.addAttribute("todayInsertUser", todayInsertUser);
        //////////////////////////////////// 用户信息 end ///////////////////////////////////
        List<UserDailyActivity> userDailyActivityList = userDailyActivityService.selectList(new EntityWrapper<>());
        int sevenLoginUser = 0;
        int monthLoginUser = 0;
        if (ObjectUtil.isNotNull(userDailyActivityList)) {
            //七天活跃
            List<UserDailyActivity> sevenUserList = userDailyActivityList.stream().filter(userDailyActivity ->
                    ChronoUnit.DAYS.between(userDailyActivity.getCreateTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate(), LocalDate.now()) <= 6).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(sevenUserList)) {
                sevenLoginUser = sevenUserList.size();
            }
            //月活跃
            List<UserDailyActivity> monthUserList = userDailyActivityList.stream().filter(userDailyActivity ->
                    isCurrentMonth(userDailyActivity.getCreateTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate())).collect(Collectors.toList());
            if (ObjectUtil.isNotNull(monthUserList)) {
                monthLoginUser = monthUserList.size();
            }
        }
        model.addAttribute("sevenLoginUser", sevenLoginUser);
        model.addAttribute("monthLoginUser", monthLoginUser);
        //用户日活/新增
        List<UsersLogin> usersLoginList = new ArrayList<>(7);
        List<LocalDate> LocalDateList = getLastSevenDays();
        for (LocalDate localDate : LocalDateList) {
            UsersLogin usersLogin = new UsersLogin();
            usersLogin.setY(localDate.toString());
            List<UserDailyActivity> userDailyActivities = userDailyActivityList.stream().filter(userDailyActivity ->
                    localDate.equals(userDailyActivity.getCreateTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate())).collect(Collectors.toList());
            int dailyActivity = 0;
            if (ObjectUtil.isNotNull(userDailyActivities)) {
                dailyActivity = userDailyActivities.size();
            }
            usersLogin.setA(dailyActivity);
            ///新增
            List<Users> usersLists = usersList.stream().filter(users ->
                    localDate.equals(users.getCreateTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate())).collect(Collectors.toList());
            int insertUser = 0;
            if (ObjectUtil.isNotNull(usersLists)) {
                insertUser = usersLists.size();
            }
            usersLogin.setB(insertUser);
            usersLoginList.add(usersLogin);
        }
        Gson gson = new Gson();
        model.addAttribute("usersLoginList", gson.toJson(usersLoginList));
        return "main";
    }

    private static boolean isCurrentMonth(LocalDate date) {
        LocalDate now = LocalDate.now();
        return date.get(ChronoField.MONTH_OF_YEAR) == now.get(ChronoField.MONTH_OF_YEAR)
                && date.get(ChronoField.YEAR) == now.get(ChronoField.YEAR);
    }

    private int totalCount(List<AdRecord> adRecordList) {
        List<AdRecord> totalList = adRecordList.stream().filter(adRecord -> DateUtil.isSameDay(adRecord.getCreateTime(), new Date())).collect(Collectors.toList());
        int totalCount = 0;
        if (ObjectUtil.isNotNull(totalList)) {
            totalCount = totalList.stream().mapToInt(AdRecord::getArRealityMoney).sum();
        }
        return totalCount;
    }

    public List<LocalDate> getLastSevenDays() {
        LocalDate today = LocalDate.now();
        return IntStream.range(0, 7)
                .mapToObj(today::minusDays)
                .collect(Collectors.toList());
    }
}
